#ifndef WXSPROPERTY_H
#define WXSPROPERTY_H

#include <wx/scrolwin.h>
#include <wx/toolbar.h>
#include <wx/stattext.h>
#include <wx/button.h>
#include <wx/dcclient.h>
#include <wx/textctrl.h>
#include <wx/propgrid/propgrid.h>
#include <wx/propgrid/manager.h>
#include <tinyxml.h>
#include <prep.h>
#include "wxspropertystream.h"

#define wxPGId                          wxPGProperty*
#define wxPGVariantToWxObjectPtr(A,B)   wxDynamicCast(A.GetWxObjectPtr(),B)
#define wxPG_PROP_UNSPECIFIED           wxPG_EX_AUTO_UNSPECIFIED_VALUES

class wxsPropertyContainer;

class wxsProperty {
  public:
    wxsProperty( const wxString & PGName, const wxString & DataName, int Priority );
    virtual ~wxsProperty() {}
    virtual void PGCreate( M_Code_unused wxsPropertyContainer *  Object, M_Code_unused wxPropertyGridManager * Grid, M_Code_unused wxPGId Parent ) {}
    virtual bool PGRead( M_Code_unused wxsPropertyContainer *  Object,
                         M_Code_unused wxPropertyGridManager * Grid,
                         M_Code_unused wxPGId Id, M_Code_unused long Index ) { return false; }
    virtual bool PGWrite( M_Code_unused wxsPropertyContainer *  Object,
                          M_Code_unused wxPropertyGridManager * Grid,
                          M_Code_unused wxPGId Id, M_Code_unused long Index ) { return false; }
    virtual bool XmlRead( M_Code_unused wxsPropertyContainer * Object,
                          M_Code_unused TiXmlElement * Element ) { return false; }
    virtual bool XmlWrite( M_Code_unused wxsPropertyContainer * Object,
                           M_Code_unused TiXmlElement * Element ) { return false; }
    virtual bool PropStreamRead( M_Code_unused wxsPropertyContainer * Object,
                                 M_Code_unused wxsPropertyStream *    Stream ) { return false; }
    virtual bool PropStreamWrite( M_Code_unused wxsPropertyContainer * Object,
                                  M_Code_unused wxsPropertyStream *    Stream ) { return false; }
    inline const wxString & GetPGName()   { return m_PGName; }
    inline const wxString & GetDataName() { return m_DataName; }
    inline int GetPriority() { return m_Priority; }
    virtual const wxString GetTypeName() = 0;
  protected:
    long PGRegister( wxsPropertyContainer * Object, wxPropertyGridManager * Grid, wxPGId ID, long Index = -1 );
    long GetPropertiesFlags( wxsPropertyContainer * Object );
    static bool XmlGetString( TiXmlElement * Elem, wxString & Value, const wxString& SubChild = wxEmptyString );
    static void XmlSetString( TiXmlElement * Elem, const wxString & Value, const wxString& SubChild = wxEmptyString );
    inline static bool XmlGetLong( TiXmlElement * Elem, long & Value, const wxString& SubChild = wxEmptyString ) {
      wxString Tmp;
      return XmlGetString( Elem, Tmp, SubChild ) && Tmp.ToLong( &Value );
    }
    static void XmlSetLong( TiXmlElement * Elem, long Value, const wxString& SubChild = wxEmptyString ) {
      XmlSetString( Elem, wxString::Format( _T( "%ld" ), Value ), SubChild );
    }
    inline static bool XmlGetBool( TiXmlElement * Elem, bool & Value, const wxString& SubChild = wxEmptyString ) {
      long Tmp;
      if( !XmlGetLong( Elem, Tmp, SubChild ) ) {
        return false;
      }
      Value = Tmp != 0;
      return true;
    }
    static void XmlSetBool( TiXmlElement * Elem, bool Value, const wxString& SubChild = wxEmptyString ) {
      XmlSetString( Elem, Value ? _T( "1" ) : _T( "0" ), SubChild );
    }
  private:
    wxString m_PGName;
    wxString m_DataName;
    int      m_Priority;
};

#define wxsOFFSET(Class,Variable) \
  ( (intptr_t)(((char*)(&(((Class*)1)->Variable)))) - \
    (intptr_t)(((char*)((wxsPropertyContainer*)((Class*)1)))) )
#define wxsVARIABLE(Instance,Offset,Type) \
  (*((Type*)(((char*)&((wxsPropertyContainer&)*(Instance)))+(Offset))))

#endif
